package org.jsola.hr.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.jsola.common.BeanKit;
import org.jsola.common.DateKit8;
import org.jsola.common.StrKit;
import org.jsola.contract.dto.ContractUpdateDTO;
import org.jsola.contract.entity.AppendixDO;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ContractFieldToString;
import org.jsola.hr.common.ExcelKit;
import org.jsola.hr.common.task.TaskKit;
import org.jsola.hr.constant.ContractDateEnum;
import org.jsola.hr.constant.FileType;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpContractDAO;
import org.jsola.hr.dto.*;
import org.jsola.hr.entity.EmpContractDO;
import org.jsola.hr.provider.IContractProviderService;
import org.jsola.hr.provider.IFileProviderService;
import org.jsola.hr.provider.INoticeProviderService;
import org.jsola.hr.query.EmpContractQuery;
import org.jsola.hr.query.EmpInfoExportColumn;
import org.jsola.hr.service.IEmpContractService;
import org.jsola.hr.service.IEmpPaperContractService;
import org.jsola.hr.service.excel.EmpContractListener;
import org.jsola.hr.task.SendNoticeTask;
import org.jsola.hr.vo.*;
import org.jsola.notice.constant.NoticeConstants;
import org.jsola.notice.vo.NoticeRuleSettingVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.core.UserContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.util.HtmlUtils;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 员工合同信息
 *
 * @author zhr
 */
@Service("hrEmpContractServiceImpl")
@Slf4j
public class EmpContractServiceImpl implements IEmpContractService {

    @Autowired
    private IEmpContractDAO empContractDAO;

    @Autowired
    private INoticeProviderService noticeProviderService;

    @Autowired
    private TaskKit taskKit;

    @Autowired
    private SendNoticeTask sendNoticeTask;
    @Autowired
    private IContractProviderService contractProviderService;
    @Autowired
    private IEmpPaperContractService empPaperContractService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpContractVO save(EmpContractAddDTO empContractAddDTO, TokenUser tokenUser) {
        if (StringUtil.isBlank(empContractAddDTO.getName())) {
            empContractAddDTO.setName("未命名合同");
        }
        // 转DO
        EmpContractDO empContractDO = empContractAddDTO.to(EmpContractDO.class);

        // 校验员工和公司
        checkEmpAndCompany(empContractDO.getEmpId(), empContractDO.getCompanyId(), tokenUser.getSiteId());

        // 保存
        empContractDO = save(empContractDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empContractDO.to(EmpContractVO.class);
    }

    @Override
    public Integer onlySave(EmpContractDO empContractDO) {
        if (StringUtil.isBlank(empContractDO.getName())) {
            empContractDO.setName("未命名合同");
        }
        return empContractDAO.insert(empContractDO);
    }

    /**
     * 校验员工和公司
     *
     * @param empId     员工id
     * @param companyId 公司id
     * @param siteId    站点
     */
    private void checkEmpAndCompany(String empId, String companyId, String siteId) {
        ParamException.hasLength(empId, "员工id不能为空");
        ParamException.hasLength(companyId, "公司id不能为空");
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<EmpContractVO> batchSave(List<EmpContractAddDTO> empContractAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(empContractAddDTOList)) {
            return null;
        }
        List<EmpContractDO> empContractDOList = empContractAddDTOList.parallelStream().map(empContractAddDTO -> {
            if (StringUtil.isBlank(empContractAddDTO.getName())) {
                empContractAddDTO.setName("未命名合同");
            }
            EmpContractDO empContractDO = empContractAddDTO.to(EmpContractDO.class);
            empContractDO.preInsert(tokenUser.getUserId());
            empContractDO.setSiteId(tokenUser.getSiteId());
            return empContractDO;
        }).collect(Collectors.toList());
        empContractDAO.insertListAndSetId(empContractDOList);
        return empContractDOList
                .parallelStream()
                .map(empContractDO -> empContractDO.to(EmpContractVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpContractUpdateDTO empContractUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpContractDO empContractDO = empContractUpdateDTO.to(EmpContractDO.class);
        // 合同对应关系不允许修改
        empContractDO.setContractId(null);
        //合同到期时间修改发送合同到期通知
        List<EmpContractDO> empContractDOS = new ArrayList<>();
        empContractDOS.add(empContractDO);
        sendContractNotice(empContractDOS);

        // 校验员工和公司
        checkEmpAndCompany(empContractDO.getEmpId(), empContractDO.getCompanyId(), tokenUser.getSiteId());
        // 修改花名册前合同信息
        EmpContractDO oldDO = selectDOById(empContractUpdateDTO.getId());
        // 关联了合同 且修改了合同名称 同步合同表
        if (oldDO.getContractId() != null) {
            ContractUpdateDTO contractUpdateDTO = new ContractUpdateDTO();
            contractUpdateDTO.setId(oldDO.getContractId());
            // 修改了名称
            if (StringUtil.isNotBlank(empContractUpdateDTO.getName())
                    && !empContractUpdateDTO.getName().equals(oldDO.getName())) {
                contractUpdateDTO.setName(empContractUpdateDTO.getName());
            }
            // 修改了备注
            if (StringUtil.isNotBlank(empContractUpdateDTO.getRemark())
                    && !empContractUpdateDTO.getRemark().equals(oldDO.getRemark())) {
                contractUpdateDTO.setContractNo(empContractUpdateDTO.getRemark());
            }
            if (empContractUpdateDTO.getName() != null || empContractUpdateDTO.getRemark() != null) {
                contractProviderService.updateContract(contractUpdateDTO, tokenUser);
            }
        }
        //根据主键更新，只更新非null值
        return updateByIdSelective(empContractDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    /**
     * 合同信息修改后，发送到期通知
     *
     * @param empContractDOS 电子合同
     */
    private void sendContractNotice(List<EmpContractDO> empContractDOS) {
        try {
            NoticeRuleSettingVO ruleSettingVO = noticeProviderService.selectByTypeCodeAndCompany(HrConstants.HR_SUBJECT_TYPE,
                    NoticeConstants.RETIRE, empContractDOS.get(0).getCompanyId());
            if (ruleSettingVO == null || ruleSettingVO.getId() == null || !ruleSettingVO.getEnableStatus()) {
                return;
            }
            Iterator<EmpContractDO> iterator = empContractDOS.iterator();
            while (iterator.hasNext()) {
                EmpContractDO next = iterator.next();
                if (next.getEndTime() == null) {
                    iterator.remove();
                    continue;
                }
                EmpContractDO empContractDO = selectDOById(next.getId());
                if (empContractDO.getEndTime() != null && DateUtil.isSameTime(empContractDO.getEndTime(), next.getEndTime())) {
                    iterator.remove();
                }
            }
            List<TaskAddDTO> taskAddDTOList = sendNoticeTask.addEmpContract(empContractDOS, new Date());
            TokenUser tokenUser = new TokenUser();
            tokenUser.setUserId("system");
            tokenUser.setSiteId(HrConstants.DEFAULT);
            taskKit.addTaskList(taskAddDTOList, tokenUser);
        } catch (Exception e) {
            log.info("合同信息修改后，发送到期通知处理失败");
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empContractIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empContractIds);
    }


    @Override
    public EmpContractVO selectById(String empContractId, String siteId) {
        EmpContractDO empContractDO = selectDOById(empContractId, siteId);
        if (empContractDO == null) {
            return null;
        }
        return empContractDO.to(EmpContractVO.class);
    }

    @Override
    public List<EmpContractListVO> select(EmpContractQuery empContractQuery, String siteId) {
        List<EmpContractDO> empContractDOList = selectDO(empContractQuery, siteId);
        if (CollectionUtils.isEmpty(empContractDOList)) {
            return empContractDOList == null ? null : new ArrayList<>();
        }
        return empContractDOList.stream()
                .map(empContractDO -> empContractDO.to(EmpContractListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<EmpContractDO> selectByDateAndType(Date publishDate, Date endDate, Integer dateline, String fileType
            , String empId, String siteId) {
        Example example = new Example(EmpContractDO.class);
        // 4要素需要完全一致 为空不能跳过判断
        if (publishDate == null) {
            example.and().andIsNull("startTime");
        } else {
            example.and().andEqualTo("startTime", publishDate);
        }
        if (endDate == null) {
            example.and().andIsNull("endTime");
        } else {
            example.and().andEqualTo("endTime", endDate);
        }
        if (fileType == null) {
            example.and().andIsNull("type");
        } else {
            example.and().andEqualTo("type", fileType);
        }
        example.and()
                .andEqualTo("siteId", siteId)
                .andEqualTo("empId", empId)
                .andEqualTo("valid", true);
        example.orderBy("gmtCreate").desc();
        List<EmpContractDO> empContractDOList = empContractDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(empContractDOList)) {
            return new ArrayList<>();
        }
        List<EmpContractDO> list = new ArrayList<>();
        for (EmpContractDO empContractDO : empContractDOList) {
            int termYear = empContractDO.getTermYear() == null ? 0 : empContractDO.getTermYear();
            int termMonth = empContractDO.getTermMonth() == null ? 0 : empContractDO.getTermMonth();
            int line = termYear * 12 + termMonth;
            if (dateline == line) {
                list.add(empContractDO);
            }
        }
        return list;
    }

    @Override
    public int selectCount(EmpContractQuery empContractQuery, String siteId) {
        Example example = buildExample(empContractQuery, siteId);
        return empContractDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpContractListVO> selectPage(EmpContractQuery empContractQuery, String siteId) {
        Example example = buildExample(empContractQuery, siteId);
        Page<EmpContractDO> page = empContractDAO.selectPageByExample(example,
                empContractQuery.getPageNo(),
                empContractQuery.getPageSize());

        return page.to(EmpContractListVO.class);
    }

    @Override
    public EmpContractDO selectDOById(String empContractId, String siteId) {
        return listById(empContractId, siteId);
    }

    @Override
    public EmpContractDO selectDOById(String empContractId) {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("id", empContractId);
        return empContractDAO.selectOneByExample(example);
    }

    @Override
    public List<EmpContractDO> selectDO(EmpContractQuery empContractQuery, String siteId) {
        Example example = buildExample(empContractQuery, siteId);
        return empContractDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param empContractQuery 查询参数
     * @param siteId           所属站点id
     * @return example
     */
    private Example buildExample(EmpContractQuery empContractQuery, String siteId) {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empContractQuery.getContractId() != null) {
            example.and().andEqualTo("contractId", empContractQuery.getContractId());
        }
        if (empContractQuery.getEmpId() != null) {
            example.and().andEqualTo("empId", empContractQuery.getEmpId());
        }
        if (empContractQuery.getType() != null) {
            example.and().andEqualTo("type", empContractQuery.getType());
        }
        if (empContractQuery.getStartTimeStart() != null &&
                empContractQuery.getStartTimeEnd() != null) {
            example.and().andBetween("startTime", empContractQuery.getStartTimeStart(),
                    empContractQuery.getStartTimeEnd());
        }
        if (empContractQuery.getEndTimeStart() != null &&
                empContractQuery.getEndTimeEnd() != null) {
            example.and().andBetween("endTime", empContractQuery.getEndTimeStart(),
                    empContractQuery.getEndTimeEnd());
        }
        if (empContractQuery.getName() != null) {
            example.and().andLike("name", "%" + empContractQuery.getName() + "%");
        }
        if (empContractQuery.getTermYear() != null) {
            example.and().andEqualTo("termYear", empContractQuery.getTermYear());
        }
        if (empContractQuery.getTermMonth() != null) {
            example.and().andEqualTo("termMonth", empContractQuery.getTermMonth());
        }
        if (empContractQuery.getTermDay() != null) {
            example.and().andEqualTo("termDay", empContractQuery.getTermDay());
        }
        if (empContractQuery.getRemark() != null) {
            example.and().andEqualTo("remark", empContractQuery.getRemark());
        }
        if (empContractQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empContractQuery.getCompanyId());
        }
        example.orderBy("gmtCreate").desc();
//        // 排序
//        ExampleKit.setExampleOrder(example,empContractQuery.getOrders());
        return example;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteByCompanyId(String companyId, TokenUser tokenUser) {

        // 逻辑删除
        List<EmpContractDO> list = listByCompanyId(companyId, tokenUser.getSiteId());
        String[] ids = list.stream()
                .map(BaseDO::getId).toArray(String[]::new);
        deleteByIds(tokenUser, ids);
    }

    /**
     * 公司下所有员工与合同关联关系
     *
     * @param companyId 公司id
     * @param siteId    站点id
     * @return 员工与合同关联关系
     */
    private List<EmpContractDO> listByCompanyId(String companyId, String siteId) {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("companyId", companyId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate").desc();
        return empContractDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void publishEmpContractList(List<EmpContractDTO> empContractList, String companyId, String empId, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(empContractList)) {
            return;
        }
        List<EmpContractAddDTO> empContractAddDTOList = new ArrayList<>();
        for (EmpContractDTO empContractDTO : empContractList) {
            empContractDTO.setCompanyId(companyId);
            empContractDTO.setEmpId(empId);
            if (empContractDTO.getId() == null) {
                // id为空是新增
                EmpContractAddDTO empContractAddDTO = empContractDTO.to(EmpContractAddDTO.class);
                empContractAddDTOList.add(empContractAddDTO);
            } else {
                // id不为空是修改
                EmpContractUpdateDTO empContractUpdateDTO = empContractDTO.to(EmpContractUpdateDTO.class);
                update(empContractUpdateDTO, tokenUser);
            }
        }
        batchSave(empContractAddDTOList, tokenUser);
    }

    @Override
    public List<EmpContractDO> listByEmpId(String empId, String siteId) {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("empId", empId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate").desc();
        return empContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpContractDO> listByType(String empId, String type, String siteId) {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("empId", empId)
                .andEqualTo("type", type)
                .andEqualTo("valid", true)
                .andIsNull("contractId")
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate").desc();
        return empContractDAO.selectByExample(example);
    }

    /**
     * 删除某个员工所有的
     *
     * @param empId     员工id
     * @param tokenUser 当前用户
     */
    private void deleteByEmpId(String empId, TokenUser tokenUser) {

        // 逻辑删除
        List<EmpContractDO> list = listByEmpId(empId, tokenUser.getSiteId());
        String[] ids = list.stream()
                .map(BaseDO::getId).toArray(String[]::new);
        deleteByIds(tokenUser, ids);
    }

    @Override
    public Map<String, List<EmpContractDO>> getEmpContractMapByCompany(String companyId, String siteId) {
        List<EmpContractDO> list = listByCompanyId(companyId, siteId);
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.groupingBy(EmpContractDO::getEmpId));
    }

    @Override
    public EmpContractDO selectByEmpIdWithGmtCreateDesc(String empId, String siteId) {
        Example example = new Example(EmpContractDO.class);
        example.and().andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empId", empId);
        example.orderBy("gmtCreate").desc();
        List<EmpContractDO> empContractDOList = empContractDAO.selectByExample(example);
        if (!CollectionUtils.isEmpty(empContractDOList)) {
            return empContractDOList.get(0);
        } else {
            return new EmpContractDO();
        }

    }

    @Override
    public List<EmpContractDO> selectByCompanyIdAndEmpIds(String companyId, List<String> empIds) {
        if (CollectionUtils.isEmpty(empIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpContractDO.class);
        example.and().andEqualTo("valid", true)
                .andEqualTo("companyId", companyId)
                .andIn("empId", empIds);
        example.orderBy("gmtCreate").desc();
        return empContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpContractDO> selectByEmpIds(List<String> empIds) {
        if (CollectionUtils.isEmpty(empIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpContractDO.class);
        example.and().andEqualTo("valid", true)
                .andIn("empId", empIds);
        example.orderBy("gmtCreate").desc();
        return empContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpContractDO> listAllNoExpireContract() {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andIsNotNull("companyId")
                .andEqualTo("valid", true)
                .andIsNotNull("endTime")
                .andGreaterThanOrEqualTo("endTime", DateKit8.getCurrentDay(DateKit8.DATE));
        return empContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpContractDO> selectByContractId(Long contractId) {
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("contractId", contractId);
        return empContractDAO.selectByExample(example);
    }

    @Override
    public List<EmpContractDO> selectByContractIds(List<Long> contractIds) {
        if (CollectionUtils.isEmpty(contractIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(EmpContractDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("contractId", contractIds);
        return empContractDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpContractExcelVO importFile(File file, TokenUser tokenUser, String companyId) {

        // 电子合同
        EmpContractListener empContractListener = new EmpContractListener();
        empContractListener.setCompanyId(companyId);
        empContractListener.setForce(true);
        empContractListener.setTokenUser(tokenUser);
        // 读取excel 并且入库
        EasyExcel.read(file, EmpContractImportDTO.class, empContractListener).sheet("电子合同").headRowNumber(2).doRead();
        EmpContractExcelVO empContractExcelVO = empContractListener.getEmpContractExcelVO();
        ParamException.notNull(empContractExcelVO, "导入失败，请检查导入模板及Sheet标签名称");
        if (!CollectionUtils.isEmpty(empContractExcelVO.getImportFailList())) {
            String excelFilePath = exportFailData(empContractExcelVO.getImportFailList());
            empContractExcelVO.setExcelFilePath(excelFilePath);
        }
        return empContractExcelVO;
    }

    @Override
    public Page<HrContractVO> pageElectronicAndPaper(EmpContractQuery empContractQuery, TokenUser tokenUser) {
        // 查询总数
        Integer count = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        // 查询List
        List<HrContractVO> hrContractVOList = empContractDAO.electronicAndPaperList(empContractQuery, tokenUser.getSiteId());
        this.setOtherInfo(hrContractVOList);
        int pageNo = empContractQuery.getPageNo();
        int pageSize = empContractQuery.getPageSize();
        // 查询文件信息
        List<Long> contractIdList = hrContractVOList.parallelStream().filter(hrContractVO
                -> hrContractVO.getIsEntity() != null && !hrContractVO.getIsEntity()).map(hrContractVO
                -> Long.parseLong(hrContractVO.getId())).collect(Collectors.toList());
        List<AppendixDO> appendixDOList = contractProviderService.appendixListByContractIds(contractIdList, tokenUser.getSiteId());
        // 合同-合同文件Map
        Map<Long, String> contractIdPathMap = appendixDOList.parallelStream().filter(appendixDO -> StringUtil
                .isNotBlank(appendixDO.getPath())).collect(Collectors.toMap(AppendixDO::getContractId, AppendixDO::getPath));
        hrContractVOList.parallelStream().forEach(hrContractVO -> {
            // 合同类型转换
            if (StringUtil.isNotBlank(hrContractVO.getConType())) {
                FileType fileType = FileType.find(hrContractVO.getConType());
                if (fileType != null) {
                    hrContractVO.setConTypeStr(fileType.getDesc());
                } else {
                    hrContractVO.setConTypeStr("其他");
                }
            } else {
                hrContractVO.setConTypeStr("其他");
            }
            if (hrContractVO.getIsEntity() != null && !hrContractVO.getIsEntity()) {
                hrContractVO.setFilePath(contractIdPathMap.get(Long.parseLong(hrContractVO.getId())));
            }
        });
        return new Page<>(hrContractVOList, pageNo, pageSize, count);
    }


    @Override
    public Page<HrContractVO> pageElectronicAndPaperForXcx(EmpContractQuery empContractQuery, TokenUser tokenUser) {
        // 查询总数
        Integer count = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        // 查询List
        List<HrContractVO> hrContractVOList = empContractDAO.electronicAndPaperListForXcx(empContractQuery, tokenUser.getSiteId());
        this.setOtherInfo(hrContractVOList);
        int pageNo = empContractQuery.getPageNo();
        int pageSize = empContractQuery.getPageSize();
        // 查询文件信息
        List<Long> contractIdList = hrContractVOList.parallelStream().filter(hrContractVO
                -> hrContractVO.getIsEntity() != null && !hrContractVO.getIsEntity()).map(hrContractVO
                -> Long.parseLong(hrContractVO.getId())).collect(Collectors.toList());
        List<AppendixDO> appendixDOList = contractProviderService.appendixListByContractIds(contractIdList, tokenUser.getSiteId());
        // 合同-合同文件Map
        Map<Long, String> contractIdPathMap = appendixDOList.parallelStream().filter(appendixDO -> StringUtil
                .isNotBlank(appendixDO.getPath())).collect(Collectors.toMap(AppendixDO::getContractId, AppendixDO::getPath));
        hrContractVOList.parallelStream().forEach(hrContractVO -> {
            // 合同类型转换
            if (StringUtil.isNotBlank(hrContractVO.getConType())) {
                FileType fileType = FileType.find(hrContractVO.getConType());
                if (fileType != null) {
                    hrContractVO.setConTypeStr(fileType.getDesc());
                } else {
                    hrContractVO.setConTypeStr("其他");
                }
            } else {
                hrContractVO.setConTypeStr("其他");
            }
            if (hrContractVO.getIsEntity() != null && !hrContractVO.getIsEntity()) {
                hrContractVO.setFilePath(contractIdPathMap.get(Long.parseLong(hrContractVO.getId())));
            }
        });
        return new Page<>(hrContractVOList, pageNo, pageSize, count);
    }

    /**
     * 设置全部合同前端需要展示的值
     */
    private void setOtherInfo(List<HrContractVO> hrContractVOList) {
        hrContractVOList.forEach(hrContractVO -> {
            if (hrContractVO.getEndDate() != null) {
                // 剩余有效时间
                long daysBetween = DateKit8.getDaysBetween(new Date(), hrContractVO.getEndDate());
                if (hrContractVO.getEndDate().compareTo(new Date()) < 0) {
                    daysBetween *= -1;
                }
                hrContractVO.setRemainingValidTime(daysBetween);
            }
            if (StrKit.isEmpty(hrContractVO.getIdCard())) {
                hrContractVO.setIdCard("身份证号未填写");
            }
            // 单位;1:年 2:月
            Integer timeLimitType = hrContractVO.getTimeLimitType();
            // 数量
            Integer timeLimit = hrContractVO.getTimeLimit();
            if (timeLimit != null && timeLimitType != null) {
                // 期限为月 若为12的倍数 转换为年
                // 合同期限
                String contractLine;
                if (timeLimitType == 2 && timeLimit % 12 == 0) {
                    contractLine = timeLimit / 12 + "年";
                } else {
                    contractLine = timeLimit
                            + ContractDateEnum.find(timeLimitType).getDesc();
                }
                hrContractVO.setContractLine(contractLine);
            }
        });
    }

    @Override
    public HrContractCountVO selectElectronicAndPaperNumber(EmpContractQuery empContractQuery, TokenUser tokenUser) {
        HrContractCountVO hrContractCountVO = new HrContractCountVO();
        String companyId = StrKit.isEmpty(empContractQuery.getCompanyId()) ? null : empContractQuery.getCompanyId();
        List<String> companyIdList = empContractQuery.getCompanyIdList();
        // 全部合同数量
        empContractQuery = new EmpContractQuery();
        empContractQuery.setCompanyId(companyId);
        empContractQuery.setCompanyIdList(companyIdList);
        int allCount = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        // 即将过期
        empContractQuery = new EmpContractQuery();
        empContractQuery.setCompanyId(companyId);
        empContractQuery.setCompanyIdList(companyIdList);
        empContractQuery.setWillExpire(true);
        int willExpireCount = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        // 已经过期
        empContractQuery = new EmpContractQuery();
        empContractQuery.setCompanyId(companyId);
        empContractQuery.setCompanyIdList(companyIdList);
        empContractQuery.setAlreadyExpire(true);
        int alreadyExpireCount = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        // 单人两份以上
        empContractQuery = new EmpContractQuery();
        empContractQuery.setCompanyId(companyId);
        empContractQuery.setCompanyIdList(companyIdList);
        empContractQuery.setExceedDouble(true);
        int exceedDoubleCount = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        // 纸质合同数量
        empContractQuery = new EmpContractQuery();
        empContractQuery.setCompanyId(companyId);
        empContractQuery.setCompanyIdList(companyIdList);
        empContractQuery.setIsEntity(true);
        int paperCount = empContractDAO.electronicAndPaperCount(empContractQuery, tokenUser.getSiteId());
        hrContractCountVO.setAllCount(allCount);
        hrContractCountVO.setWillExpireCount(willExpireCount);
        hrContractCountVO.setAlreadyExpireCount(alreadyExpireCount);
        hrContractCountVO.setExceedDoubleCount(exceedDoubleCount);
        hrContractCountVO.setPaperCount(paperCount);
        return hrContractCountVO;
    }

    @Override
    public String exportAllContract(EmpContractQuery empContractQuery, TokenUser tokenUser) {
        empContractQuery.setPageNo(null);
        empContractQuery.setPageSize(null);
        ParamException.notEmpty(empContractQuery.getExportColumns(), "没有需要导出的表头，请调整检索条件");
        // 查询List
        List<HrContractVO> hrContractVOList = empContractDAO.electronicAndPaperList(empContractQuery,
                tokenUser.getSiteId());
        ParamException.notEmpty(hrContractVOList, "没有需要导出的数据，请调整检索条件");
        this.setOtherInfo(hrContractVOList);
        // 表头为中文名，所以需要再定义一个英文名的集合，准备反射获取属性
        List<List<String>> headList = new ArrayList<>();
        // 表头英文名集合
        List<String> headPropertyList = new ArrayList<>();
        // 定义所有的数据集合
        List<List<String>> dataList = new ArrayList<>();
        for (EmpInfoExportColumn empInfoExportColumn : empContractQuery.getExportColumns()) {
            // 定义每一个表头
            List<String> oneHead = new ArrayList<>();
            oneHead.add(empInfoExportColumn.getTitle());
            headList.add(oneHead);
            headPropertyList.add(empInfoExportColumn.getDataIndex());
        }
        for (HrContractVO hrContractVO : hrContractVOList) {
            // 定义每一条数据
            List<String> oneData = new ArrayList<>();
            //循环表头,往每一条数据中，拼装数据
            for (String head : headPropertyList) {
                Field field;
                try {
                    field = hrContractVO.getClass().getDeclaredField(head);
                } catch (NoSuchFieldException e) {
                    log.error("表头传入错误：heard：{}", head);
                    throw new ParamException("表头传入错误");
                }
                field.setAccessible(true);
                try {
                    if (field.get(hrContractVO) != null) {
                        if ("class java.util.Date".equals(field.getGenericType().toString())) {
                            // 日期类型
                            Date date = (Date) field.get(hrContractVO);
                            oneData.add(DateKit8.format2Date(date));
                        } else {
                            String value = ContractFieldToString.fieldToStringAllContract(field, hrContractVO);
                            oneData.add(value);
                        }
                    } else {
                        oneData.add("");
                    }
                } catch (IllegalAccessException e) {
                    log.error("表头传入错误：heard：{}", head);
                    throw new ParamException("表头传入错误");
                }
            }
            dataList.add(oneData);
        }
        return ExcelKit.exportExcelDynamic(empContractQuery.getEnName(), "合同导出", dataList, headList);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer deleteBatchElectronicAndPaperNumber(EmpAllContractDeleteDTO[] empAllContractDeleteDTOS, TokenUser tokenUser) {
        // 电子合同纸质合同分类
        List<Long> electronicIds = new ArrayList<>();
        List<String> paperIds = new ArrayList<>();
        for (EmpAllContractDeleteDTO empAllContractDeleteDTO : empAllContractDeleteDTOS) {
            if (empAllContractDeleteDTO.getIsEntity() == null || StrKit.isEmpty(empAllContractDeleteDTO.getId())) {
                throw new ParamException("id和类型都不能为空!");
            }
            if (empAllContractDeleteDTO.getIsEntity()) {
                paperIds.add(empAllContractDeleteDTO.getId());
            } else {
                electronicIds.add(Long.parseLong(empAllContractDeleteDTO.getId()));
            }
        }
        int count = 0;
        // 删除电子合同
        if (!CollectionUtils.isEmpty(electronicIds)) {
            count += contractProviderService.deleteContractByIds(tokenUser,
                    electronicIds.toArray(new Long[0]));
        }

        // 删除纸质合同
        if (!CollectionUtils.isEmpty(paperIds)) {
            count += empPaperContractService.deleteByIds(tokenUser,
                    paperIds.toArray(new String[0]));
        }
        return count;
    }


    /**
     * 导出错误数据
     */
    private String exportFailData(List<EmpContractImportDTO> importFailList) {
        // 导出excel
        String excelFilePath = ExcelKit.exportExcel("empContract", "电子合同",
                EmpContractImportDTO.class, importFailList);
        String cleanPath = org.springframework.util.StringUtils.cleanPath(excelFilePath);
        File file = new File(excelFilePath);
        log.info("本地路径：" + file.getPath());

        FileItem fileItem = createFileItem(file);
        CommonsMultipartFile[] commonsMultipartFiles = new CommonsMultipartFile[1];
        commonsMultipartFiles[0] = new CommonsMultipartFile(fileItem);
        String fileName = "电子合同导入错误数据-" + DateUtil.format(new Date(), "yyyy.MM.dd");
        TokenUser tokenUser = UserContext.getUser();

        IFileProviderService fileProviderService = BeanKit.getBean(IFileProviderService.class);
        List<String> list =
                fileProviderService.uploadAndSetName(commonsMultipartFiles, "inline", fileName, tokenUser);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * File 转 FileItem
     */
    private FileItem createFileItem(File file) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }

}




